package com.yingjia.yingjiauniversity.utils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.List;

/**
 * <处理泛型相关>
 *
 * @author: guoxiangxun
 * @date: 15 -12-18 下午6:35
 * @version: v1.0
 */
public class GenericReflectUtil {


    /**
     * <返回泛型参数的数组>
     *
     * @param subclass the subclass
     * @return the type [ ]
     * @author: guoxiangxun
     * @date: Dec 18, 2015 6:36:20 PM
     * @version: v1.0
     */
    public static Type[] getSuperclassTypeParameter(Class<?> subclass) {
        Type superclass = subclass.getGenericSuperclass();
        if (superclass instanceof Class) {
            throw new RuntimeException("Missing type parameter.");
        }
        ParameterizedType parameterized = (ParameterizedType) superclass;

        return parameterized.getActualTypeArguments();
    }

    /**
     * Gets param type identify.获取泛型type的名称，可以由多个类型组成
     *
     * @param mType the m type
     * @return the param type identify
     */
    public static String getGenericTypeName(Type mType) {
        String name = "";

        if (mType != null) {
            if (mType instanceof Class) {
                name = ((Class) mType).getName();
            } else if (mType instanceof ParameterizedType) {
                Type[] actualTypeArguments = ((ParameterizedType) mType).getActualTypeArguments();
                for (Type t : actualTypeArguments) {
                    name += getGenericTypeName(t);
                }
            } else if (mType instanceof TypeVariable) {
                Type mType1 = ((TypeVariable) mType).getBounds()[0];
                name = getGenericTypeName(mType1);
            }
        }

        return name;
    }


    /**
     * <通过type获取class>
     *
     * @param mType the m type
     * @return the param clazz
     * @author: guoxiangxun
     * @date: Dec 18, 2015 2:16:07 PM
     * @version: v1.0
     */
    public static Class getClazz(Type mType) {
        Class clazz = null;
        if (mType != null) {
            if (mType instanceof Class) {
                clazz = (Class) mType;
            } else if (mType instanceof ParameterizedType) {
                clazz = (Class) ((ParameterizedType) mType).getRawType();
            } else if (mType instanceof TypeVariable) {
                Type mType1 = ((TypeVariable) mType).getBounds()[0];
                clazz = getClazz(mType1);
            }
        }

        return clazz;
    }

    /**
     * 获取所有的泛型数据
     *
     * @param type
     * @return
     */
    public static List<Class<?>> getGenericTypes(Type type) {
        List<Class<?>> rootList = new ArrayList<Class<?>>();
        if (type instanceof ParameterizedType) {
            ParameterizedType pType = (ParameterizedType) type;
            rootList.add((Class<?>) pType.getRawType());
            for (Type at : pType.getActualTypeArguments()) {
                List<Class<?>> childList = getGenericTypes(at);
                rootList.addAll(childList);
            }
        } else {
            rootList.add((Class<?>) type);
        }
        return rootList;
    }
}
